﻿#region Copyright (c) 2013-05, Olaf Kober <amarok.projects@gmail.com>
//================================================================================
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//================================================================================
#endregion

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using Amarok.Agents;


namespace Amarok.Presentation
{
	/// <summary>
	/// This interface represents the window manager, which provides access to the presentation system.
	/// </summary>
	public interface IWindowManager
	{
		#region CheckAccess, VerifyAccess

		/// <summary>
		/// Determines whether the calling thread has access to the user interface.
		/// </summary>
		/// 
		/// <returns>
		/// True if the calling thread has access to the user interface; otherwise, False.</returns>
		Boolean CheckAccess();

		/// <summary>
		/// Enforces that the calling thread has access to the user interface.
		/// </summary>
		/// 
		/// <exception cref="InvalidOperationException">
		/// The calling thread does not have access to the user interface.</exception>
		void VerifyAccess();

		#endregion

		#region Invoke(Action)

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		void Invoke(Action callback);

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		void Invoke(Action callback, DispatcherPriority priority);

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// <param name="cancellationToken">
		/// An object that indicates whether to cancel the callback.</param>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		void Invoke(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);

		#endregion

		#region InvokeAsync(Action)

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task InvokeAsync(Action callback);

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task InvokeAsync(Action callback, DispatcherPriority priority);

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// <param name="cancellationToken">
		/// An object that indicates whether to cancel the callback.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);

		#endregion

		#region Invoke(Func<T>)

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// 
		/// <returns>
		/// The return value of the specified callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		T Invoke<T>(Func<T> callback);

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// 
		/// <returns>
		/// The return value of the specified callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		T Invoke<T>(Func<T> callback, DispatcherPriority priority);

		/// <summary>
		/// Executes the specified callback synchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// <param name="cancellationToken">
		/// An object that indicates whether to cancel the callback.</param>
		/// 
		/// <returns>
		/// The return value of the specified callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		T Invoke<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);

		#endregion

		#region InvokeAsync(Action)

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task<T> InvokeAsync<T>(Func<T> callback);

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority);

		/// <summary>
		/// Executes the specified callback asynchronously on the user interface thread.
		/// </summary>
		/// 
		/// <typeparam name="T">
		/// The type of the return value returned from the specified callback.</typeparam>
		/// 
		/// <param name="callback">
		/// The callback to execute, which takes no arguments and does not return a value.</param>
		/// <param name="priority">
		/// The priority that determines in what order the specified callback is invoked relative to 
		/// other pending operations.</param>
		/// <param name="cancellationToken">
		/// An object that indicates whether to cancel the callback.</param>
		/// 
		/// <returns>
		/// A task that represents the asynchronously running callback. This task can be used to wait for completion, 
		/// to register a continuation and to access the state of the callback.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);

		#endregion

		#region ShowWindow(WindowDescription)

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <param name="windowDescription">
		/// The window description that specifies which window should be shown.</param>
		/// <param name="environment">
		/// The agent environment that should be forwarded to the window's controller.</param>
		/// <param name="options">
		/// The agent options that should be forwarded to the window's controller.</param>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		ICompletable ShowWindow(WindowDescription windowDescription, AgentEnvironment environment, AgentOptions options);

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <param name="windowDescription">
		/// The window description that specifies which window should be shown.</param>
		/// <param name="options">
		/// The agent options that should be forwarded to the window's controller.</param>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		ICompletable ShowWindow(WindowDescription windowDescription, AgentOptions options);

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		ICompletable ShowWindow(WindowDescription windowDescription);

		#endregion

		#region ShowWindow<T>()

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <param name="environment">
		/// The agent environment that should be forwarded to the window's controller.</param>
		/// <param name="options">
		/// The agent options that should be forwarded to the window's controller.</param>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		ICompletable ShowWindow<TWindowDescription>(AgentEnvironment environment, AgentOptions options)
			where TWindowDescription : WindowDescription, new();

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <param name="options">
		/// The agent options that should be forwarded to the window's controller.</param>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		/// 
		/// <exception cref="ArgumentNullException">
		/// A null reference was passed to a method that did not accept it as a valid argument.</exception>
		ICompletable ShowWindow<TWindowDescription>(AgentOptions options)
			where TWindowDescription : WindowDescription, new();

		/// <summary>
		/// Shows a non-modal window specified by the supplied window description. This method automatically 
		/// switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <returns>
		/// The method returns the <see cref="ICompletable"/> reference of the window description, which 
		/// can be used to tear down the window and associated controller.</returns>
		ICompletable ShowWindow<TWindowDescription>()
			where TWindowDescription : WindowDescription, new();

		#endregion

		#region Exit()

		/// <summary>
		/// Shuts down the application. This method automatically switches into the user interface thread 
		/// to complete the request, if necessary.
		/// </summary>
		void Exit();

		/// <summary>
		/// Shuts down an application that returns the specified exit code to the operating system. This 
		/// method automatically switches into the user interface thread to complete the request, if necessary.
		/// </summary>
		/// 
		/// <param name="exitCode">
		/// An integer exit code for an application. The default exit code is 0.</param>
		void Exit(Int32 exitCode);

		#endregion

	}
}
